package design_pattern.Singleton;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/23 14:41
 * @Version 1.0
 *
 * 单例、懒加载、性能好
 */
public class SingletonObject4 {
    private static volatile SingletonObject4 instance;
    private SingletonObject4(){

    }
    // double check ==> 但是会造成一个问题，在多线程重排序后，会造成空指针异常。
    // 原因：当一个线程进来后 发现instance不为null，就new了一个放入堆中，但是这个时候 new的这个对象它的成员变量附属属性还没有初始化完成，
    //另外一个线程就来拿这个对象了，但是它的成员变量还没有初始化成功，所以会报错空指针异常。
    // 造成这种原因：java 进行的优化和重排序
    // 解决方案：加volatile， private static volatile SingletonObject4 instance;
    // volatile 虽然不能保证原子性，但是能够内存可见
    private static SingletonObject4 getInstance()
    {
        if(instance == null){
            // 相比于3 这种方式好处就是，不在方法上加锁，锁的是某一部分代码
            synchronized (SingletonObject4.class){
                if(instance == null){
                    // 如果instance 加上volatile之后，那么下面，new一个对象后，就代表真正完成了（所有工作都好了，不存在编译重新编排）
                    // volatile 在对这个变量读的过程之前必定有一个写的过程。
                    instance = new SingletonObject4();
                }
            }
        }
        return instance;
    }
}
